#!/usr/bin/env python3
"""
HTTPS后端服务器
解决HTTPS前端无法访问HTTP后端的混合内容问题
"""

import ssl
import sys
import os
import socket
from pathlib import Path

# 添加项目根目录到Python路径
project_root = Path(__file__).parent
sys.path.insert(0, str(project_root))

# 导入主应用
from main import app

def get_local_ip():
    """获取本机局域网IP地址"""
    try:
        # 创建一个UDP socket来获取本机IP
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s.connect(("8.8.8.8", 80))
        ip = s.getsockname()[0]
        s.close()
        return ip
    except Exception:
        return "127.0.0.1"

def create_ssl_context(cert_file, key_file):
    """创建SSL上下文"""
    try:
        context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
        context.load_cert_chain(cert_file, key_file)
        
        # 设置安全选项
        context.options |= ssl.OP_NO_SSLv2
        context.options |= ssl.OP_NO_SSLv3
        context.options |= ssl.OP_NO_TLSv1
        context.options |= ssl.OP_NO_TLSv1_1
        
        # 设置密码套件
        context.set_ciphers('ECDHE+AESGCM:ECDHE+CHACHA20:DHE+AESGCM:DHE+CHACHA20:!aNULL:!MD5:!DSS')
        
        return context
    except Exception as e:
        print(f"❌ SSL上下文创建失败: {e}")
        return None

def generate_self_signed_cert(cert_file, key_file, hostname="localhost"):
    """生成自签名证书（如果不存在）"""
    try:
        from cryptography import x509
        from cryptography.x509.oid import NameOID
        from cryptography.hazmat.primitives import hashes
        from cryptography.hazmat.primitives.asymmetric import rsa
        from cryptography.hazmat.primitives import serialization
        import datetime
        import ipaddress
        
        # 生成私钥
        private_key = rsa.generate_private_key(
            public_exponent=65537,
            key_size=2048,
        )
        
        # 创建证书主题
        subject = issuer = x509.Name([
            x509.NameAttribute(NameOID.COUNTRY_NAME, "CN"),
            x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, "Beijing"),
            x509.NameAttribute(NameOID.LOCALITY_NAME, "Beijing"),
            x509.NameAttribute(NameOID.ORGANIZATION_NAME, "Vision Pro AI"),
            x509.NameAttribute(NameOID.COMMON_NAME, hostname),
        ])
        
        # 创建证书
        cert = x509.CertificateBuilder().subject_name(
            subject
        ).issuer_name(
            issuer
        ).public_key(
            private_key.public_key()
        ).serial_number(
            x509.random_serial_number()
        ).not_valid_before(
            datetime.datetime.utcnow()
        ).not_valid_after(
            datetime.datetime.utcnow() + datetime.timedelta(days=365)
        ).add_extension(
            x509.SubjectAlternativeName([
                x509.DNSName("localhost"),
                x509.DNSName("127.0.0.1"),
                x509.IPAddress(ipaddress.IPv4Address("127.0.0.1")),
                x509.IPAddress(ipaddress.IPv4Address(get_local_ip())),
            ]),
            critical=False,
        ).sign(private_key, hashes.SHA256())
        
        # 保存证书
        with open(cert_file, "wb") as f:
            f.write(cert.public_bytes(serialization.Encoding.PEM))
        
        # 保存私钥
        with open(key_file, "wb") as f:
            f.write(private_key.private_bytes(
                encoding=serialization.Encoding.PEM,
                format=serialization.PrivateFormat.PKCS8,
                encryption_algorithm=serialization.NoEncryption()
            ))
        
        print(f"✅ 自签名证书已生成: {cert_file}")
        return True
        
    except ImportError:
        print("❌ 需要安装cryptography库来生成证书: pip install cryptography")
        return False
    except Exception as e:
        print(f"❌ 证书生成失败: {e}")
        return False

def main():
    """主函数"""
    import argparse
    
    parser = argparse.ArgumentParser(description='HTTPS后端服务器')
    parser.add_argument('--port', type=int, default=8000, help='服务器端口 (默认: 8000)')
    parser.add_argument('--host', type=str, default='0.0.0.0', help='服务器主机 (默认: 0.0.0.0)')
    parser.add_argument('--cert', type=str, help='SSL证书文件路径')
    parser.add_argument('--key', type=str, help='SSL私钥文件路径')
    parser.add_argument('--generate-cert', action='store_true', help='生成自签名证书')
    
    args = parser.parse_args()
    
    # 确定证书文件路径
    if args.cert and args.key:
        cert_file = args.cert
        key_file = args.key
    else:
        # 使用前端目录的证书文件
        frontend_dir = project_root / "frontend"
        cert_file = frontend_dir / "server.crt"
        key_file = frontend_dir / "server.key"
    
    # 检查证书文件是否存在
    if not cert_file.exists() or not key_file.exists():
        if args.generate_cert:
            print("🔧 正在生成自签名证书...")
            if not generate_self_signed_cert(cert_file, key_file):
                print("❌ 证书生成失败，退出")
                sys.exit(1)
        else:
            print(f"❌ 证书文件不存在: {cert_file} 或 {key_file}")
            print("💡 使用 --generate-cert 参数自动生成证书")
            sys.exit(1)
    
    # 创建SSL上下文
    ssl_context = create_ssl_context(cert_file, key_file)
    if not ssl_context:
        print("❌ SSL上下文创建失败，退出")
        sys.exit(1)
    
    # 获取本机IP
    local_ip = get_local_ip()
    
    print("🚀 启动HTTPS后端服务器...")
    print(f"📁 项目根目录: {project_root}")
    print(f"🔒 SSL证书: {cert_file}")
    print(f"🔑 SSL私钥: {key_file}")
    print(f"🌐 本地访问: https://localhost:{args.port}")
    print(f"🌍 网络访问: https://{local_ip}:{args.port}")
    print(f"💡 API端点: https://localhost:{args.port}/api/")
    print(f"🔍 健康检查: https://localhost:{args.port}/health")
    print("=" * 50)
    
    try:
        # 启动HTTPS服务器
        import uvicorn
        uvicorn.run(
            "main:app",
            host=args.host,
            port=args.port,
            ssl_keyfile=str(key_file),
            ssl_certfile=str(cert_file),
            log_level="info",
            reload=False
        )
    except KeyboardInterrupt:
        print("\n👋 服务器已停止")
    except Exception as e:
        print(f"❌ 服务器启动失败: {e}")
        sys.exit(1)

if __name__ == "__main__":
    main()